using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace TheLogWatcher
{
    public partial class MainWindow : Form
    {

        /// <summary>
        ///     This method is used when a logfile is loaded for the first time.
        /// </summary>
        /// <param name="filename"></param>
        private bool LoadLogfile(string filename)
        {
            // Close previous session
            toolStripFileClose_Click(null, null);

            FileOpenManager openMan = new FileOpenManager(this.data);
            this.dataAccess = openMan.OpenFileFirstTime(filename);
            if (this.dataAccess == null)
            {
                HistoryOrganizer_RemoveEntry(filename);
                return false;
            }
            ProgressWindow progWin = new ProgressWindow(this.dataAccess);
            bool everythingOk = progWin.RunFileIndexer();

            if (everythingOk)
            {
                // Set title of application with loaded file
                string title = filename.Substring(filename.LastIndexOf('\\') + 1);
                this.Text = "The Log Watcher - " + title;
                this.toolStripStatusLabel.Text = "Entries: ";

                // Update statusbar "All Entries"
                RedrawListView();

                // Updates the history menu
                HistoryOrganizer_AddEntry(filename);

                // Register file change watcher
                FileInfo info = new FileInfo(filename);
                fileSystemWatcher.Path = info.DirectoryName;
                fileSystemWatcher.Filter = info.Name;

                // Set date filter range
                dateTimePicker1.Value = dataAccess.DateFirstEntry;
                dateTimePicker1.MinDate = dataAccess.DateFirstEntry.Date;
                dateTimePicker1.MaxDate = dataAccess.DateLastEntry.Date.AddDays(1);
                dateTimePicker2.Value = dataAccess.DateLastEntry;
                dateTimePicker2.MinDate = dataAccess.DateFirstEntry.Date;
                dateTimePicker2.MaxDate = dataAccess.DateLastEntry.Date.AddDays(1);
            }
            else
            {
                // Delete entry from history menu if it exists
                HistoryOrganizer_RemoveEntry(filename);
            }

            // SETTING LISTVIEW COLUMNS
            if (this.dataAccess != null && this.dataAccess.CurrentLogFormat != null)
            {
                string logName = this.dataAccess.CurrentLogFormat.Name;
                this.colMan = new ColumnManager(this.listView, logName);
                CreateListViewContextMenuItems();
            }

            this.listView.VirtualMode = true;
            return everythingOk;
        }


        private void ActivateType(MessageTypes type)
        {
            sets.SelectedTypes.Add(type.ToString());
            sets.Save();

            // Iterator settings for active row reload operations
            setListViewVirtualMode();
        }

        private void DeactivateType(MessageTypes type)
        {
            sets.SelectedTypes.Remove(type.ToString());
            // Iterator settings for active row reload operations
            setListViewVirtualMode();
        }

        /// <summary>
        ///     Checks if virtual mode is required for list view
        ///     and fulfils several jobs in return.
        /// </summary>
        private void setListViewVirtualMode()
        {
            this.listView.Items.Clear();
            if (this.dataAccess == null || this.dataAccess.SortedIndices == null)
            {
                Console.WriteLine("Cannot set virtual list view size, indices are null.");
                this.listView.VirtualListSize = 0;
                return;
            }
            this.listView.VirtualListSize = this.dataAccess.SortedIndices.Count;
        }

        private void listView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
        {
            e.Item = RetrieveNeededListViewItem(e.ItemIndex);
        }

        private ListViewItem RetrieveNeededListViewItem(int i)
        {
            LogEntry entry = RetrieveNeededEntry(i);
            if (entry != null)
            {
                // Create listview item from log entry
                ListViewItem item = Utilities.getListViewItem(entry, this.dataAccess.CurrentLogFormat);
                return item;
            }
            ListViewItem errorItem = new ListViewItem("---");
            errorItem.SubItems.Add("---");
            errorItem.SubItems.Add("---");
            errorItem.SubItems.Add("FAILED TO LOAD ENTRY");
            errorItem.SubItems.Add("---");
            return errorItem;
        }

        public LogEntry RetrieveNeededEntry(int entryIndex)
        {
            if (this.dataAccess.SortedIndices.Count <= entryIndex || entryIndex < 0)
            {
                Console.WriteLine("RetrieveNeededEntry: Index out of range.");
                return null;
            }
            IndexObject neededEntry = this.dataAccess.SortedIndices[entryIndex];
            LogEntry entry = RetrieveNeededEntry(neededEntry);
            return entry;
        }

        private LogEntry RetrieveNeededEntry(IndexObject neededEntry)
        {
            long fileStreamStartPos = neededEntry.FileIndex;
            long fileStreamEndPos = -1;
            // Use next entry's start position as end
            LinkedListNode<long> node = this.dataAccess.IndicesByFileIndex.Find(fileStreamStartPos);
            if (node != null && node.Next != null && node.Next.Value!=0)
            {
                fileStreamEndPos = node.Next.Value;
            }

            if (fileStreamEndPos != -1 && fileStreamStartPos > fileStreamEndPos)
            {
                Console.WriteLine("RetrieveNeededEntry: Start pos > end pos. Invalid entry...");
                return null;
            }
            AccessReaderHandler readerHandler = new AccessReaderHandler(this.data, this.dataAccess);
            LogEntry entry = readerHandler.readEntry(neededEntry.MessageType, fileStreamStartPos, fileStreamEndPos);
            return entry;
        }

    }
}

